package com.rpframework.module.common.bottom.controller;

import com.rpframework.core.json.FailException;
import com.rpframework.core.json.LoginExpiredException;
import com.rpframework.core.json.ServletThreadLocal;
import com.rpframework.module.common.bottom.entity.enums.RequestType;
import com.rpframework.module.common.bottom.entity.enums.SourceType;
import com.rpframework.module.common.domain.UserLogin;
import com.rpframework.module.common.service.UserTokenService;
import com.rpframework.module.common.springmvc.bind.DateEditor;
import com.rpframework.module.common.url.RequestDescription;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

import static com.rpframework.core.json.ServletThreadLocal.getResponse;
import static com.rpframework.module.common.bottom.entity.enums.SourceType.addLoginCookie;

@RequestDescription("基本控制层")
@Controller
public class BaseController {

    protected final Logger log = LoggerFactory.getLogger(getClass());

    public BaseController() {
    }

    @Autowired
    public BaseController(UserTokenService userTokenService) {
        this.userTokenService = userTokenService;
    }

    /**
     * 由于Spring在接受前台传入的List时，<br>
     * 就会出现256的IndexOutOfBoundsException异常 <br>
     * 设置setAutoGrowCollectionLimit为1024
     *
     * @param binder 目标
     * @see [类、类#方法、类#成员]
     */
    @InitBinder
    public void initListBinder(WebDataBinder binder) {
        // 设置需要包裹的元素个数，默认为256
        binder.setAutoGrowCollectionLimit(4096);
    }

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Date.class, new DateEditor());
    }

    @Autowired
    protected UserTokenService userTokenService;


    /**
     * 获取用户主键
     *
     * @param source 来源
     * @return 主键
     */
    public Long getUserId(HttpServletRequest request, SourceType source) {
        source = SourceType.sourceInit(request, source);
        String token = SourceType.getToken(request, source);

        if (StringUtils.isBlank(token)) {
            throw new LoginExpiredException("用户令牌没有找到");
        }

        String userId = userTokenService.checkToken(token, source);
        if (StringUtils.isBlank(userId)) {
            throw new LoginExpiredException("用户令牌已过期");
        }
        try {
            return Long.parseLong(userId);
        } catch (Exception e) {
            throw new FailException("服务器出错了");
        }
    }

    /**
     * 获取用户令牌
     *
     * @return 令牌
     */
    public String getToken() {
        return SourceType.getToken(ServletThreadLocal.getRequest());
    }

    /**
     * 获取登录来源
     *
     * @return 来源
     */
    public SourceType getSource() {
        return SourceType.parse(ServletThreadLocal.getRequest());
    }

    /**
     * 获取登录信息
     *
     * @return 来源不同信息不同
     */
    protected UserLogin getUserLogin() {
        SourceType source = getSource();
        UserLogin userLogin = new UserLogin();
        userLogin.setSource(source);
        userLogin.setToken(SourceType.getToken(ServletThreadLocal.getRequest(), source));
        return userLogin;
    }

    /**
     * 删除token在缓存
     *
     * @param type 来源
     */
    public void removeTokenByCookie(SourceType type) {
        addLoginCookie(type, getResponse(), "NULL", 0);
    }

    /**
     * 获取用户主键
     *
     * @param source 来源
     * @return 主键
     */
    public Long getUserId(SourceType source) {
        return getUserId(ServletThreadLocal.getRequest(), source);
    }

    /**
     * 获取用户主键
     *
     * @return 主键
     */
    public Long getUserId() {
        return getUserId(SourceType.parse(ServletThreadLocal.getRequest()));
    }

    /**
     * 获取用户主键
     *
     * @return 主键
     */
    public Long getUserId(HttpServletRequest request) {
        return getUserId(request, null);
    }

    /**
     * 获取后台用户的用户主键
     *
     * @param loginPage 是否跳转登陆页面
     * @return 用户主键
     */
    public Long getUserIdAdmin(HttpServletRequest request, HttpServletResponse response,
                               String loginPage) {
        try {
            return getUserId(request, SourceType.ADMIN);
        } catch (LoginExpiredException ignored) {
            try {
                if (!StringUtils.isBlank(loginPage)) {
                    response.sendRedirect(request.getContextPath() + RequestType.PAGE.getUriFix() + loginPage);
                } else {
                    throw ignored;
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return null;
    }

    /**
     * 获取后台用户的用户主键
     * * @return 用户主键
     */
    public Long getUserIdAdmin(HttpServletRequest request) {
        return getUserIdAdmin(request, null, null);
    }

    /**
     * 获取后台用户的用户主键
     * * @return 用户主键
     */
    public Long getUserIdAdmin() {
        return getUserIdAdmin(ServletThreadLocal.getRequest(), null, null);
    }

}
